package com.ibm.rules;

import java.math.BigInteger;

import com.google.common.collect.Range;
import com.ibm.cps.message.ParsedDataMessage;
import com.ibm.datamodel.timeseries.TimeSeriesSchema;

public class Rule {

	@SuppressWarnings("rawtypes")
	private RuleEntry[] entries;
	private BigInteger ruleID;

	@SuppressWarnings("rawtypes")
	public Rule(BigInteger ruleID, RuleEntry[] entryList) {
		this.ruleID = ruleID;
		this.entries = entryList;
	}

	public Rule(Rule rule) {
		this.ruleID = rule.getRuleID();
		this.entries = rule.getEntries().clone();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean eval(Comparable[] v) {
		for (int i = 0; i < entries.length; ++i) {
			if (entries[i] == null) {
				continue;
			}
			if (v[entries[i].getTagId()] == null
					|| !entries[i].eval(v[entries[i].getTagId()])) {
				return false;
			}
		}
		return true;
	}
	
	// add by gxj to support array 
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean eval(ParsedDataMessage msg) {
		for (int i = 0; i < entries.length; ++i) {
			if (entries[i] == null) {
				continue;
			}
			int tagid = entries[i].getTagId();
			if (tagid >= 0) {
				Comparable value = (Comparable) msg.getValue(tagid);
				if (value == null || !entries[i].eval(value)) {
					return false;
				}
			}else {
				// tagid is a array contain index
				int[] indexs = TimeSeriesSchema.parseTagId(tagid);
				int index = indexs[0];
				int subindex = indexs[1];
				Object[] values = (Object[]) msg.getArrayValue(index);
				if (values == null) {
					return false;
				}
				Comparable value = (Comparable) values[subindex];
				if (value == null | !entries[i].eval(value)) {
					return false;
				}
			}
		}
		return true;
	}

	public BigInteger getRuleID() {
		return ruleID;
	}

	public Range getRangeByTagId(int tagId) {
		for (int i = 0; i < entries.length; i++) {
			if (entries[i].getTagId() == tagId) {
				return entries[i].getRange();
			}
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	public RuleEntry[] getEntries() {
		return entries;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void eraseCondition(int tagId, Range range) {
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null && entries[i].getTagId() == tagId) {
				if (range.encloses(entries[i].getRange()))
					entries[i] = null;
				break;
			}
		}
	}

	public Rule refine() {
		return null;
	}

	@Override
	public int hashCode() {
		return ruleID.intValue();
	}

	@Override
	public boolean equals(Object des) {
		if (!(des instanceof Rule)) {
			return false;
		}
		Rule dr = (Rule) des;
		// TODO: compare the conditions of the two rules
		return false;
	}
}
